home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / sparc / include / asm / checksum_32.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  6.7 KB  |  242 lines

  1. #ifndef __SPARC_CHECKSUM_H
  2. #define __SPARC_CHECKSUM_H
  3.  
  4. /*  checksum.h:  IP/UDP/TCP checksum routines on the Sparc.
  5.  *
  6.  *  Copyright(C) 1995 Linus Torvalds
  7.  *  Copyright(C) 1995 Miguel de Icaza
  8.  *  Copyright(C) 1996 David S. Miller
  9.  *  Copyright(C) 1996 Eddie C. Dost
  10.  *  Copyright(C) 1997 Jakub Jelinek
  11.  *
  12.  * derived from:
  13.  *    Alpha checksum c-code
  14.  *      ix86 inline assembly
  15.  *      RFC1071 Computing the Internet Checksum
  16.  */
  17.  
  18. #include <linux/in6.h>
  19. #include <asm/uaccess.h>
  20.  
  21. /* computes the checksum of a memory block at buff, length len,
  22.  * and adds in "sum" (32-bit)
  23.  *
  24.  * returns a 32-bit number suitable for feeding into itself
  25.  * or csum_tcpudp_magic
  26.  *
  27.  * this function must be called with even lengths, except
  28.  * for the last fragment, which may be odd
  29.  *
  30.  * it's best to have buff aligned on a 32-bit boundary
  31.  */
  32. extern __wsum csum_partial(const void *buff, int len, __wsum sum);
  33.  
  34. /* the same as csum_partial, but copies from fs:src while it
  35.  * checksums
  36.  *
  37.  * here even more important to align src and dst on a 32-bit (or even
  38.  * better 64-bit) boundary
  39.  */
  40.  
  41. extern unsigned int __csum_partial_copy_sparc_generic (const unsigned char *, unsigned char *);
  42.  
  43. static inline __wsum
  44. csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
  45. {
  46.     register unsigned int ret asm("o0") = (unsigned int)src;
  47.     register char *d asm("o1") = dst;
  48.     register int l asm("g1") = len;
  49.  
  50.     __asm__ __volatile__ (
  51.         "call __csum_partial_copy_sparc_generic\n\t"
  52.         " mov %6, %%g7\n"
  53.     : "=&r" (ret), "=&r" (d), "=&r" (l)
  54.     : "0" (ret), "1" (d), "2" (l), "r" (sum)
  55.     : "o2", "o3", "o4", "o5", "o7",
  56.       "g2", "g3", "g4", "g5", "g7",
  57.       "memory", "cc");
  58.     return (__force __wsum)ret;
  59. }
  60.  
  61. static inline __wsum
  62. csum_partial_copy_from_user(const void __user *src, void *dst, int len,
  63.                 __wsum sum, int *err)
  64.   {
  65.     register unsigned long ret asm("o0") = (unsigned long)src;
  66.     register char *d asm("o1") = dst;
  67.     register int l asm("g1") = len;
  68.     register __wsum s asm("g7") = sum;
  69.  
  70.     __asm__ __volatile__ (
  71.     ".section __ex_table,#alloc\n\t"
  72.     ".align 4\n\t"
  73.     ".word 1f,2\n\t"
  74.     ".previous\n"
  75.     "1:\n\t"
  76.     "call __csum_partial_copy_sparc_generic\n\t"
  77.     " st %8, [%%sp + 64]\n"
  78.     : "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
  79.     : "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
  80.     : "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5",
  81.       "cc", "memory");
  82.     return (__force __wsum)ret;
  83. }
  84.  
  85. static inline __wsum
  86. csum_partial_copy_to_user(const void *src, void __user *dst, int len,
  87.               __wsum sum, int *err)
  88. {
  89.     if (!access_ok (VERIFY_WRITE, dst, len)) {
  90.         *err = -EFAULT;
  91.         return sum;
  92.     } else {
  93.         register unsigned long ret asm("o0") = (unsigned long)src;
  94.         register char __user *d asm("o1") = dst;
  95.         register int l asm("g1") = len;
  96.         register __wsum s asm("g7") = sum;
  97.  
  98.         __asm__ __volatile__ (
  99.         ".section __ex_table,#alloc\n\t"
  100.         ".align 4\n\t"
  101.         ".word 1f,1\n\t"
  102.         ".previous\n"
  103.         "1:\n\t"
  104.         "call __csum_partial_copy_sparc_generic\n\t"
  105.         " st %8, [%%sp + 64]\n"
  106.         : "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
  107.         : "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
  108.         : "o2", "o3", "o4", "o5", "o7",
  109.           "g2", "g3", "g4", "g5",
  110.           "cc", "memory");
  111.         return (__force __wsum)ret;
  112.     }
  113. }
  114.  
  115. #define HAVE_CSUM_COPY_USER
  116. #define csum_and_copy_to_user csum_partial_copy_to_user
  117.  
  118. /* ihl is always 5 or greater, almost always is 5, and iph is word aligned
  119.  * the majority of the time.
  120.  */
  121. static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
  122. {
  123.     __sum16 sum;
  124.  
  125.     /* Note: We must read %2 before we touch %0 for the first time,
  126.      *       because GCC can legitimately use the same register for
  127.      *       both operands.
  128.      */
  129.     __asm__ __volatile__("sub\t%2, 4, %%g4\n\t"
  130.                  "ld\t[%1 + 0x00], %0\n\t"
  131.                  "ld\t[%1 + 0x04], %%g2\n\t"
  132.                  "ld\t[%1 + 0x08], %%g3\n\t"
  133.                  "addcc\t%%g2, %0, %0\n\t"
  134.                  "addxcc\t%%g3, %0, %0\n\t"
  135.                  "ld\t[%1 + 0x0c], %%g2\n\t"
  136.                  "ld\t[%1 + 0x10], %%g3\n\t"
  137.                  "addxcc\t%%g2, %0, %0\n\t"
  138.                  "addx\t%0, %%g0, %0\n"
  139.                  "1:\taddcc\t%%g3, %0, %0\n\t"
  140.                  "add\t%1, 4, %1\n\t"
  141.                  "addxcc\t%0, %%g0, %0\n\t"
  142.                  "subcc\t%%g4, 1, %%g4\n\t"
  143.                  "be,a\t2f\n\t"
  144.                  "sll\t%0, 16, %%g2\n\t"
  145.                  "b\t1b\n\t"
  146.                  "ld\t[%1 + 0x10], %%g3\n"
  147.                  "2:\taddcc\t%0, %%g2, %%g2\n\t"
  148.                  "srl\t%%g2, 16, %0\n\t"
  149.                  "addx\t%0, %%g0, %0\n\t"
  150.                  "xnor\t%%g0, %0, %0"
  151.                  : "=r" (sum), "=&r" (iph)
  152.                  : "r" (ihl), "1" (iph)
  153.                  : "g2", "g3", "g4", "cc", "memory");
  154.     return sum;
  155. }
  156.  
  157. /* Fold a partial checksum without adding pseudo headers. */
  158. static inline __sum16 csum_fold(__wsum sum)
  159. {
  160.     unsigned int tmp;
  161.  
  162.     __asm__ __volatile__("addcc\t%0, %1, %1\n\t"
  163.                  "srl\t%1, 16, %1\n\t"
  164.                  "addx\t%1, %%g0, %1\n\t"
  165.                  "xnor\t%%g0, %1, %0"
  166.                  : "=&r" (sum), "=r" (tmp)
  167.                  : "0" (sum), "1" ((__force u32)sum<<16)
  168.                  : "cc");
  169.     return (__force __sum16)sum;
  170. }
  171.  
  172. static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
  173.                            unsigned short len,
  174.                            unsigned short proto,
  175.                            __wsum sum)
  176. {
  177.     __asm__ __volatile__("addcc\t%1, %0, %0\n\t"
  178.                  "addxcc\t%2, %0, %0\n\t"
  179.                  "addxcc\t%3, %0, %0\n\t"
  180.                  "addx\t%0, %%g0, %0\n\t"
  181.                  : "=r" (sum), "=r" (saddr)
  182.                  : "r" (daddr), "r" (proto + len), "0" (sum),
  183.                    "1" (saddr)
  184.                  : "cc");
  185.     return sum;
  186. }
  187.  
  188. /*
  189.  * computes the checksum of the TCP/UDP pseudo-header
  190.  * returns a 16-bit checksum, already complemented
  191.  */
  192. static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
  193.                            unsigned short len,
  194.                            unsigned short proto,
  195.                            __wsum sum)
  196. {
  197.     return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
  198. }
  199.  
  200. #define _HAVE_ARCH_IPV6_CSUM
  201.  
  202. static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
  203.                       const struct in6_addr *daddr,
  204.                       __u32 len, unsigned short proto,
  205.                       __wsum sum)
  206. {
  207.     __asm__ __volatile__ (
  208.         "addcc    %3, %4, %%g4\n\t"
  209.         "addxcc    %5, %%g4, %%g4\n\t"
  210.         "ld    [%2 + 0x0c], %%g2\n\t"
  211.         "ld    [%2 + 0x08], %%g3\n\t"
  212.         "addxcc    %%g2, %%g4, %%g4\n\t"
  213.         "ld    [%2 + 0x04], %%g2\n\t"
  214.         "addxcc    %%g3, %%g4, %%g4\n\t"
  215.         "ld    [%2 + 0x00], %%g3\n\t"
  216.         "addxcc    %%g2, %%g4, %%g4\n\t"
  217.         "ld    [%1 + 0x0c], %%g2\n\t"
  218.         "addxcc    %%g3, %%g4, %%g4\n\t"
  219.         "ld    [%1 + 0x08], %%g3\n\t"
  220.         "addxcc    %%g2, %%g4, %%g4\n\t"
  221.         "ld    [%1 + 0x04], %%g2\n\t"
  222.         "addxcc    %%g3, %%g4, %%g4\n\t"
  223.         "ld    [%1 + 0x00], %%g3\n\t"
  224.         "addxcc    %%g2, %%g4, %%g4\n\t"
  225.         "addxcc    %%g3, %%g4, %0\n\t"
  226.         "addx    0, %0, %0\n"
  227.         : "=&r" (sum)
  228.         : "r" (saddr), "r" (daddr),
  229.           "r"(htonl(len)), "r"(htonl(proto)), "r"(sum)
  230.         : "g2", "g3", "g4", "cc");
  231.  
  232.     return csum_fold(sum);
  233. }
  234.  
  235. /* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
  236. static inline __sum16 ip_compute_csum(const void *buff, int len)
  237. {
  238.     return csum_fold(csum_partial(buff, len, 0));
  239. }
  240.  
  241. #endif /* !(__SPARC_CHECKSUM_H) */
  242.